home *** CD-ROM | disk | FTP | other *** search
- /*
- File: FlipEnd.cpp
-
- Contains: routines to manipulate endianness of memory
-
- Owned by: David McCusker
-
- Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
-
-
- */
-
- #ifndef _FLIPEND_
- #include "FlipEnd.h"
- #endif
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- /*=========================================================================*/
- /* ODUShort endianness flipping */
- /*=========================================================================*/
-
- ODUShort ODFlipShort(ODUShort n)
- /* n is a single 2-byte int; return it with flipped endianness */
- {
- /* note it is unorthodox, but legal, to modify stack arguments */
- register ODUShort* p = &n;
-
- char c = *(char*) p;
- *(char*) p = ((char*) p)[1];
- ((char*) p)[1] = c;
-
- return *p;
- }
-
- void ODFlipShortArray(register ODUShort* n, unsigned long count)
- /* n points to count 2-byte ints; flip each int's endianness */
- {
- register char c;
- ODUShort* end = n + count; /* one past the end */
-
- --n;
- while (++n < end)
- {
- c = *(char*) n;
- *(char*) n = ((char*) n)[1];
- ((char*) n)[1] = c;
- }
- }
-
- /*=========================================================================*/
- /* ODULong endianness flipping */
- /*=========================================================================*/
-
- ODULong ODFlipLong(ODULong n)
- /* n is a single 4-byte int; return it with flipped endianness */
- {
- /* note it is unorthodox, but legal, to modify stack arguments */
- register ODULong* p = &n;
-
- register char c = *(char*) p;
- *(char*) p = ((char*) p)[3];
- ((char*) p)[3] = c;
-
- c = ((char*) p)[1];
- ((char*) p)[1]= ((char*) p)[2];
- ((char*) p)[2] = c;
-
- return *p;
- }
-
- void ODFlipLongArray(register ODULong* n, unsigned long count)
- /* n points to count 4-byte ints; flip each int's endianness */
- {
- register char c;
- ODULong* end = n + count; /* one past the end */
-
- --n;
- while (++n < end)
- {
- c = *(char*) n;
- *(char*) n = ((char*) n)[3];
- ((char*) n)[3] = c;
-
- c = ((char*) n)[1];
- ((char*) n)[1]= ((char*) n)[2];
- ((char*) n)[2] = c;
- }
- }
-
- /*=========================================================================*/
- /* structure endianness flipping */
- /*=========================================================================*/
-
- void ODFlipStruct(void* structure, const short* groups)
- /* Invert the endianness of the contents of memory in structure
- * according to the layout described by groups, which should
- * be a zero-terminated array of shorts, where each short describes
- * the size of the next chunk of memory in structure to be processed.
- * A negative value -x in the groups array indicates a block
- * of endianness-neutral memory, like a string, and causes x bytes
- * of memory to be skipped over. A positive value x in the groups
- * array indicates an x byte block of memory which should have its
- * bytes flipped end for end. Only positive values in the set
- * { 2, 4, 8 } are handled. (Other positive values are handled like
- * negative values: space is skipped). Example:
- *
- * struct Foo {
- * short alpha;
- * long beta;
- * char gamma[8];
- * long delta;
- * };
- * const short fooGroups[] = {
- * 2, // alpha
- * 4, // beta
- * -8, // gamma
- * 4, // delta
- * 0, // zero-termination
- * };
- */
- {
- register char* p = (char*) structure;
- register char c;
-
- short g = *groups++; /* next groups entry */
-
- while (g)
- {
- /* we expect 2 and 4 to be the most common values */
- if (g == 2)
- {
- c = *p; *p = p[1]; p[1] = c;
- p += 2;
- }
- else if (g == 4)
- {
- /* swap bytes 0 and 3 */
- c = *p; *p = p[3]; p[3] = c;
-
- ++p; /* swap bytes 1 and 2 */
- c = *p; *p = p[1]; p[1] = c;
-
- p += 3;
- }
- else if (g == 8)
- {
- /* swap bytes 0 and 7 */
- c = *p; *p = p[7]; p[7] = c;
-
- ++p; /* swap bytes 1 and 6 */
- c = *p; *p = p[5]; p[5] = c;
-
- ++p; /* swap bytes 2 and 5 */
- c = *p; *p = p[3]; p[3] = c;
-
- ++p; /* swap bytes 3 and 4 */
- c = *p; *p = p[1]; p[1] = c;
-
- p += 5;
- }
- else if (g < 0)
- p += -g;
- else
- p += g;
-
- g = *groups++;
- }
- }
-
- #ifdef __cplusplus
- }
- #endif
-